package com.nuanshui.heatedloan.fund.biz.service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.nuanshui.framework.consts.TransactionManagerType;
import com.nuanshui.framework.lang.MoneyUtil;
import com.nuanshui.framework.middleware.mq.MQMessage;
import com.nuanshui.framework.middleware.mq.MessageType;
import com.nuanshui.framework.utils.LogUtil;
import com.nuanshui.heatedloan.baseservice.facade.OrderNumGenerate;
import com.nuanshui.heatedloan.baseservice.service.CommonServiceImpl;
import com.nuanshui.heatedloan.constant.AccountBillBizType;
import com.nuanshui.heatedloan.constant.CrowdFundStatusType;
import com.nuanshui.heatedloan.constant.FundActionState;
import com.nuanshui.heatedloan.constant.GlobalParam;
import com.nuanshui.heatedloan.fund.biz.dal.mapper.UserAccountBillMapper;
import com.nuanshui.heatedloan.fund.biz.dal.mapper.UserCrowdfundingMapper;
import com.nuanshui.heatedloan.fund.biz.dal.mapper.UserFundActionMapper;
import com.nuanshui.heatedloan.fund.constant.AccountBillStatus;
import com.nuanshui.heatedloan.fund.enums.PlatformEnum;
import com.nuanshui.heatedloan.fund.facade.CrowdfundingService;
import com.nuanshui.heatedloan.fund.model.UserAccountBill;
import com.nuanshui.heatedloan.fund.model.UserCrowFunding;
import com.nuanshui.heatedloan.fund.model.UserFundAction;
import com.nuanshui.heatedloan.fund.vo.CrowdfundingPriceVO;
import com.nuanshui.heatedloan.fund.vo.CrowdfundingVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.*;
import java.util.Map.Entry;


@Service
@Transactional(value=TransactionManagerType.FUND_TRANSACTION_MANAGER)
public class CrowdfundingServiceImpl extends CommonServiceImpl implements CrowdfundingService{
	
	@Autowired
	private UserCrowdfundingMapper userCrowdfundingMapper;

	@Reference(url = GlobalParam.BASESERVICE_DUBBO_SERVER, timeout = GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.BASESERVICE_DUBBO_SERVER_VERSION)
	private OrderNumGenerate orderNumGenerate;
	
	@Autowired
	private UserFundActionMapper userFundActionMapper; 
	
	@Autowired
	private UserAccountBillMapper userAccountBillMapper;
	
	private String name_suffix = "收益";
	private static final Logger  logger = LoggerFactory.getLogger("user_crowdfunding");

	@Override
	public Map<String, Object> getUserCrowdfundingInfo(String currentUserId) {
		Map<String, Object> map = new HashMap<String, Object>();
		Integer investmentMoney = userCrowdfundingMapper.getUserInvestmentMoney(currentUserId);
		Integer expectEarning = userCrowdfundingMapper.getUserExpectEarning(currentUserId);
		Integer totalEarning = userCrowdfundingMapper.getUserTotalEarning(currentUserId);
		if (investmentMoney == null) investmentMoney = 0;
		if (expectEarning == null) expectEarning = 0;
		if (totalEarning == null) totalEarning = 0;
		LogUtil.info(logger, "获取用户众筹相关资金成功。投资中金额" + investmentMoney + "元。预期总收益"
				+ expectEarning +"元。历史总收益" + totalEarning +"元");
		map.put("investmentMoney", MoneyUtil.toDoubleString(investmentMoney.longValue()));//投资中金额
		map.put("expectEarning", MoneyUtil.toDoubleString(expectEarning.longValue()));//预期总收益
		map.put("totalEarning", MoneyUtil.toDoubleString(totalEarning.longValue()));//历史总收益
		//用户最近认购的众筹项目
		CrowdfundingVO crowdfundingVO = userCrowdfundingMapper.getUserLatelyCrowdfunding(currentUserId);
		if (crowdfundingVO != null) map.put("crowdfundingVO", crowdfundingVO);
		return map;
	}

	@Override
	public List<CrowdfundingVO> getCrowdfundingList(String currentUserId) {
		List<CrowdfundingVO> list = new ArrayList<CrowdfundingVO>();
		List<CrowdfundingVO> subscribeOverCrowdfundingList = new ArrayList<CrowdfundingVO>();
		List<CrowdfundingVO> subscribeCrowdfundingList = new ArrayList<CrowdfundingVO>();
		//认购中众筹
		List<CrowdfundingVO> underwayCrowdfundingList = userCrowdfundingMapper.getUnderwayCrowdfundingList();
		if (underwayCrowdfundingList != null) {
			for (CrowdfundingVO crowdfundingVO : underwayCrowdfundingList) {
				//已经认购的资金额
				Integer money = userCrowdfundingMapper.getSubscribeMoneyByCrowdfundingId(crowdfundingVO.getId());
				if (money == null) money = 0;
				crowdfundingVO.setRemainingMoney(crowdfundingVO.getTargetAmount()-money);
				if (crowdfundingVO.getRemainingMoney() <= 0) {
					crowdfundingVO.setSubscribeStatus(1);
					//添加到结束的集合中
					subscribeOverCrowdfundingList.add(crowdfundingVO);
				} else {//否则，添加到进行中的众筹
					subscribeCrowdfundingList.add(crowdfundingVO);
				}
			}
		}
		//认购结束众筹
		List<CrowdfundingVO> OverCrowdfundingList = userCrowdfundingMapper.getOverCrowdfundingList();
		if(subscribeCrowdfundingList != null) list.addAll(subscribeCrowdfundingList);
		if (subscribeOverCrowdfundingList != null) list.addAll(subscribeOverCrowdfundingList);
		if(OverCrowdfundingList != null) list.addAll(OverCrowdfundingList);
		for (CrowdfundingVO crowdfundingVO : list) {//判断用户有没有达到购买上限
			Integer buyGrades= userCrowdfundingMapper.getGardesByUserId(currentUserId, crowdfundingVO.getId());
			if (buyGrades == null) buyGrades = 0;
			//将金额转换为元
			crowdfundingVO.setStartAmount(crowdfundingVO.getStartAmount()/100);
			crowdfundingVO.setBuyGrades(buyGrades);
			if (crowdfundingVO.getLimitGrades() == -1) {
				crowdfundingVO.setIsBuyLimit(false);
			} else if (buyGrades < crowdfundingVO.getLimitGrades()) {
				crowdfundingVO.setIsBuyLimit(false);
			} else if (buyGrades >= crowdfundingVO.getLimitGrades()) {
				crowdfundingVO.setIsBuyLimit(true);
			}
		}
		
		Collections.sort(list,new Comparator<CrowdfundingVO>() {

			@Override
			public int compare(CrowdfundingVO o1, CrowdfundingVO o2) {
				int status = o1.getSubscribeStatus() - o2.getSubscribeStatus();
				
				if(status == 0 && o1.getSubscribeStatus() == 0){
					if(!o1.getIsBuyLimit()&&o2.getIsBuyLimit()) return -1;
					return 0;
				}else {
					return status;
				}
			}
		});
		return list;
	}

	@Override
	public List<CrowdfundingVO> getUserCrowdfundingRecords(Integer type, String currentUserId) {
		List<CrowdfundingVO> list = new ArrayList<CrowdfundingVO>();
		List<CrowdfundingVO> crowdfundingVOs = null;
		List<CrowdfundingVO> futureCrowdfundingVOs = null;
		List<CrowdfundingVO> underwayCrowdfundingVOs =null;
		List<CrowdfundingVO> overCrowdfundingVOs = null;
		if (type == 0) {  //全部众筹记录
			crowdfundingVOs = userCrowdfundingMapper.getCrowdfundingByUserId(currentUserId);
			LogUtil.info(logger, "已经获取用户的全部众筹记录");
		} else if (type == 1) { //投资中的众筹记录
			//获取用户认购的即将开始的众筹
			futureCrowdfundingVOs = userCrowdfundingMapper.getFutureCrowdfundingByUserId(currentUserId);
			//获取用户认购的已经开始的众筹
			underwayCrowdfundingVOs = userCrowdfundingMapper.getUnderwayCrowdfundingByUserId(currentUserId);
			LogUtil.info(logger, "已经获取用户的投资中的众筹记录");
		} else if(type == 2) {  //已经结算的众筹记录
			//获取用户认购的结束的众筹
			overCrowdfundingVOs = userCrowdfundingMapper.getOverCrowdfundingByUserId(currentUserId);
			LogUtil.info(logger, "已经获取用户的已经结束的众筹记录");
		} else {
			LogUtil.info(logger, "type="+type+".传入的值错误");
			error("type=" + type +"的值错误。");
		}
		if (crowdfundingVOs != null) list.addAll(crowdfundingVOs);
		if (futureCrowdfundingVOs != null) list.addAll(futureCrowdfundingVOs);
		if (underwayCrowdfundingVOs != null) list.addAll(underwayCrowdfundingVOs);
		if (overCrowdfundingVOs != null) list.addAll(overCrowdfundingVOs);
		for(CrowdfundingVO vo :list) {
			if(vo.getExpectEarning()!=null) {
				vo.setShowExpectEarning(MoneyUtil.toDoubleString(vo.getExpectEarning().longValue()));
			}
			moneyUtil(vo);		
		}
		return list;
	}

	@Override
	public CrowdfundingVO getCrowdfunding(String crowdfundingId, String currentUserId) {
		//获取众筹详情
		CrowdfundingVO crowdfundingVO = userCrowdfundingMapper.getCrowdfundingById(crowdfundingId);
		Integer buyGrades= userCrowdfundingMapper.getGardesByUserId(currentUserId, crowdfundingId);
		if(buyGrades == null) buyGrades = 0;
		crowdfundingVO.setBuyGrades(buyGrades);
		if (crowdfundingVO.getLimitGrades() == -1) {
			crowdfundingVO.setIsBuyLimit(false);
		} else if (buyGrades < crowdfundingVO.getLimitGrades()) {
			crowdfundingVO.setIsBuyLimit(false);
		} else if (buyGrades >= crowdfundingVO.getLimitGrades()) {
			crowdfundingVO.setIsBuyLimit(true);
		}
		//已经认购的资金额
		Integer money = userCrowdfundingMapper.getSubscribeMoneyByCrowdfundingId(crowdfundingId);
		if (money == null) money = 0;
		//剩余可投资金
		crowdfundingVO.setRemainingMoney(crowdfundingVO.getTargetAmount()-money);
		if (crowdfundingVO.getRemainingMoney() <= 0) crowdfundingVO.setSubscribeStatus(1);
		//转换金额
		crowdfundingVO = moneyUtil(crowdfundingVO);
		return crowdfundingVO;
	}
	
	/**
	 * 金额转换
	 * @param 
	 * @author zhangqing
	 * @date 2016年3月9日 上午11:12:21
	 * @since 2.5.0
	 */
	public CrowdfundingVO moneyUtil(CrowdfundingVO crowdfundingVO) {
		//将金额转换为元
		if (crowdfundingVO.getStartAmount() != null) 
			crowdfundingVO.setStartAmount(crowdfundingVO.getStartAmount()/100);
		if (crowdfundingVO.getExpectEarning() != null) 
			crowdfundingVO.setExpectEarning(crowdfundingVO.getExpectEarning()/100);
		if (crowdfundingVO.getRealEarning() != null) 
			crowdfundingVO.setRealEarning(crowdfundingVO.getRealEarning()/100);
		if (crowdfundingVO.getSubscribeMoney() != null) 
			crowdfundingVO.setSubscribeMoney(crowdfundingVO.getSubscribeMoney()/100);
		if (crowdfundingVO.getTargetAmount() != null) 
			crowdfundingVO.setTargetAmount(crowdfundingVO.getTargetAmount()/100);
		if (crowdfundingVO.getRemainingMoney() != null) 
			crowdfundingVO.setRemainingMoney(crowdfundingVO.getRemainingMoney()/100);
		return crowdfundingVO;
	}

	/**
	 * 创建用户众筹
	 * @param money 花费的金额
	 * @param crowFundId  购买的众筹id
	 * @author guohao
	 * @date 2016年3月9日 上午11:08:31
	 */
	@Override
	@Transactional(value=TransactionManagerType.FUND_TRANSACTION_MANAGER)
	public String createUserCrowdFunding(Long money,String crowFundId, String currentUserId) {	

		CrowdfundingVO vo =  userCrowdfundingMapper.getCrowdfundingById(crowFundId);
		if(vo == null) error("认购的众筹不存在");
		Integer buyTotalCount = userCrowdfundingMapper.getBuyCount(crowFundId);
		if(buyTotalCount == null) buyTotalCount = 0;
		long buyCount =  money/vo.getStartAmount();
		buyTotalCount=(int) (buyTotalCount+buyCount);
		if(vo.getTotalGrades()<buyTotalCount) error("此众筹已售罄");	
		if(buyCount<=0) error("至少买一份");
		String dealNum = orderNumGenerate.getOrderNum(AccountBillBizType.CROWD_FUNDING,4);

		UserCrowFunding userCrowFunding = new UserCrowFunding();
		userCrowFunding.setCrowdFundingId(crowFundId);
		//计算预期收益
		long earning = calcEarnings(money,vo.getBlackoutPeriod(), vo.getAnnualYield());
	    userCrowFunding.setExpectEarning(earning);
	    userCrowFunding.setGrades((buyCount));
	    userCrowFunding.setUserId(currentUserId);
	    userCrowFunding.setStatus(CrowdFundStatusType.CREATE);	    
	    userCrowFunding.setSubscribeMoney(money);
	    userCrowFunding.setDealNum(dealNum);
	    userCrowdfundingMapper.insertUserCrowdFunding(userCrowFunding);	
	    //发布失效的消息
	    MQMessage mqMessage = new MQMessage();
	    mqMessage.setType(MessageType.FAIL_CROWD_FUNDING);
		mqMessage.setBody(dealNum);
		//messageSend.send(mqMessage);
	    return  dealNum;
	    
	}
	/**
	 * 计算收益
	 * @param  money 购买的金额
	 * @Param days  众筹的封闭期
	 * @param earningsRate 收益率
	 * @author guohao
	 * @date 2016年3月9日 下午12:10:00
	 */
	private long calcEarnings(long money,long  days,long earningsRate) {
		MathContext mc = new MathContext(10, RoundingMode.HALF_DOWN);
		BigDecimal result =  BigDecimal.valueOf(money).multiply(BigDecimal.valueOf(days)).multiply(BigDecimal.valueOf(earningsRate));
		LogUtil.info(logger,(result.longValue()/10000/365)+"");
		result = result.divide(BigDecimal.valueOf(365),mc);
		result = result.divide(BigDecimal.valueOf(10000),mc);
		return result.longValue();
	}
	
	
	public static void main(String[] args) {
		
	}

	/**
	 * 确认购买的众筹
	 * @param 
	 * @author guohao
	 * @date 2016年3月9日 下午2:17:21
	 */
	@Override
	@Transactional(value=TransactionManagerType.FUND_TRANSACTION_MANAGER)
	public boolean confirmBuyCrowdFunding(String dealNum,String  platform) {
		userCrowdfundingMapper.updateUserCrowdFundingStatus(CrowdFundStatusType.BUY_SUCCESS, dealNum);
		userCrowdfundingMapper.updateplatform(platform, dealNum);
		return true;
	}

	@Override
	public UserCrowFunding getUserCrowdfundingByDealnum(String dealNum) {
	
		return  userCrowdfundingMapper.getUserCrowdfundingByDealnum(dealNum);
	}

	
	/**
	 * 把未支付的设置为失效状态
	 * @param 
	 * @author guohao
	 * @date 2016年3月9日 下午3:08:59
	 * @since 2.5.0
	 */
	@Override
	@Transactional(value=TransactionManagerType.FUND_TRANSACTION_MANAGER)
	public void failUserCrowdfunding(String dealNum) {
		UserCrowFunding userCrowFunding = getUserCrowdfundingByDealnum(dealNum);
		if(userCrowFunding.getStatus() == CrowdFundStatusType.CREATE) {
			userCrowdfundingMapper.updateUserCrowdFundingStatus(CrowdFundStatusType.FAIL, dealNum);
		}
	}

	@Override
	public Date getCreatedAtTime() {
		return userCrowdfundingMapper.getCreatedAtTime();
	}

	
	@Override
	public CrowdfundingVO getCrowdfundingSimpleInfo(String crowdfundingId) {
		CrowdfundingVO crowdfundingVO = userCrowdfundingMapper.getCrowdfundingById(crowdfundingId);
		Integer buyTotalCount = userCrowdfundingMapper.getBuyCount(crowdfundingId);
		Integer count = crowdfundingVO.getTotalGrades()-buyTotalCount;
		crowdfundingVO.setRemainingGrades(count);
		return crowdfundingVO;
	}

	/**
	 * 1、查询需结算的众筹记录
	 * 2、userId+crowdFundingId 唯一标识结算单，并生成 用户余额变动记录表（添加记录） + 账单记录表（添加记录）
	 * @author fuxinlin
	 * @date 2016年4月15日下午12:04:03
	 * @return
	 */
	@Override
	public synchronized boolean settleCrowdfunding() {
		List<UserCrowFunding> userCrowFundingList = userCrowdfundingMapper.getCurrentUnstopedCrowFunding();
		
		Map<String,List<UserCrowFunding>> groupByCrowFuIdMap = new HashMap<String, List<UserCrowFunding>>();
		
		for(UserCrowFunding ucf : userCrowFundingList){
			String key = ucf.getUserId() + ":" + ucf.getCrowdFundingId();
			List<UserCrowFunding> subUserCrowFundingList = null;
			if(groupByCrowFuIdMap.containsKey(key)){
				subUserCrowFundingList = groupByCrowFuIdMap.get(key);
				subUserCrowFundingList.add(ucf);
			}else{
				subUserCrowFundingList = new ArrayList<UserCrowFunding>();
				subUserCrowFundingList.add(ucf);
				groupByCrowFuIdMap.put(key, subUserCrowFundingList);
			}
		}
		
		if(logger.isInfoEnabled()){
			logger.info("众筹总记录数：" + groupByCrowFuIdMap.size() + "...........开始结算众筹..........");
		}
		for(Entry<String,List<UserCrowFunding>> entry : groupByCrowFuIdMap.entrySet()){
			List<UserCrowFunding> subUserCrowFundingList = entry.getValue();
			Long money = 0L;
			String[] key = entry.getKey().split(":");
			String userId = key[0]; String crowdFundingId = key[1];
			for(UserCrowFunding ucf : subUserCrowFundingList){
				money += (ucf.getExpectEarning() + ucf.getSubscribeMoney()) * ucf.getGrades();
				userCrowdfundingMapper.updateUserCrowdFundingStatus(CrowdFundStatusType.COMPLETE, ucf.getDealNum());
				if(logger.isInfoEnabled()){
					logger.info("交易号：" + ucf.getDealNum() + " 结算完成.");
				}
			}
			String dealNum = orderNumGenerate.getOrderNum(AccountBillBizType.CROWD_FUNDING,4);
			Date currentDate = new Date();			
			//余额变动记录
			UserFundAction ufa = new UserFundAction();
			ufa.setMoney(money);
			//ufa.setActionType(FundActionType.CROWD_FUNDING);
//			ufa.setCreatedAt(currentDate);
			ufa.setUserId(userId);
			ufa.setStatus(FundActionState.COMPLETE);
			ufa.setPlatform(PlatformEnum.PLATFORM_WX.getName());
			ufa.setDealNum(dealNum);
			userFundActionMapper.saveUserFundAction(ufa);
			
			//账单记录
			UserAccountBill uab = new UserAccountBill();
			uab.setMoney(money);
//			uab.setCreatedAt(currentDate);
			uab.setUserId(userId);
			uab.setStatus(AccountBillStatus.COMPLETE);
			uab.setPlatform(PlatformEnum.PLATFORM_YE.getName());
			uab.setDealNum(dealNum);
			//uab.setType(AccountBillType.CROWD_FUNDING);
			
			uab.setCheckTime(currentDate);
			uab.setName(getCrowdfundingSimpleInfo(crowdFundingId).getName() + name_suffix); 
			userAccountBillMapper.insertBillRecord(uab);
		}
		
		if(logger.isInfoEnabled()){
			logger.info("........众筹结算结束............");
		}
		
//		throw new RuntimeException("rollback");
		return true;
	}

	@Override
	public CrowdfundingPriceVO loadCrowdfundingPriceVOByDealnum(
			String settleDealNum) {
		
		
		return userCrowdfundingMapper.loadCrowdfundingPriceVOByDealnum(settleDealNum);
	}
	@Override
	public CrowdfundingVO getNewcrowdfunding(){
		return userCrowdfundingMapper.getNewcrowdfunding();
	}
}
